using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Web.UI.Design;

using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ClinicalTrials;
using PHSRAG.Utility;

namespace PHSRAG.Insight21.InsightWebControls.ClinicalTrials
{
	/// <summary>
	/// The Budget Staff Control is used to provide a user interface for a single Budget Staff.
	/// </summary>
	[ToolboxData("<{0}:BudgetStaffControl runat=server></{0}:BudgetStaffControl>"),Designer(typeof(BudgetStaffControlDesigner))]
	public class BudgetStaffControl : System.Web.UI.Control, INamingContainer
	{
      #region Instance Variables
      private BudgetStaff budgetStaff;
      private TableRow tr;
      private TableCell tdRole;
      private TableCell tdRate;
      private TableCell tdHours;
      private TableCell tdDelete;
      private DropDownList rolesList;
      private TextBox inputRate;
      private TextBox inputRole;
      private CheckBox delete;
      private RegularExpressionValidator rateFormatValidator;
      private RequiredFieldValidator rateRequiredValidator;
      private RequiredFieldValidator roleValidator;
      private RequiredFieldValidator otherRoleValidator;
      #endregion

      #region Public Properties
      /// <summary>
      /// Delete indicator
      /// </summary>
      public bool Delete
      {
         get
         {
            return delete.Checked;
         }
      }

      /// <summary>
      /// Other role text
      /// </summary>
      public string OtherRoleText
      {
         get
         {
            return inputRole.Text;
         }
      }

      /// <summary>
      /// Rate
      /// </summary>
      public string Rate
      {
         get
         {
            return inputRate.Text;
         }
      }

      /// <summary>
      /// Role Meaning
      /// </summary>
      public string RoleMeaning
      {
         get
         {
            return rolesList.SelectedItem.Text;
         }
      }

        /// <summary>
        /// "N/A" Person Indicator
        /// </summary>
        public bool IsNAPerson
        {
            get
            {
                return budgetStaff.StudyStaffRoleMeaning == "N/A";
            }
        }
      #endregion

      #region Constructor
      /// <summary>
      /// Sets the private Budget Staff member from the passed in parameter
      /// </summary>
      /// <param name="budgetStaff"></param>
      public BudgetStaffControl( BudgetStaff budgetStaff )
      {
         this.budgetStaff = budgetStaff;
      }
      #endregion

      #region Overrides
      /// <summary>
      /// Runs upon loading of the control
      /// </summary>
      /// <param name="e"></param>
      protected override void OnLoad(EventArgs e)
      {
         base.OnLoad(e);
         EnsureChildControls( );
      }

      /// <summary>
      /// Creates all child controls, applying styles, setting values, and binding validation
      /// </summary>
      protected override void CreateChildControls( )
      {
         Budget budget = (Budget)((Policy.ICachePolicy)Page.Session[Policy.Names.CachePolicyKey]).GetCachedObject( Budget.CacheKey );

         rolesList = new DropDownList( );
         inputRate = new TextBox( );
         inputRate.ID = "inputRate";
         inputRole = new TextBox( );
         inputRole.ID = "inputRole";
         delete = new CheckBox( );

         // Load the Roles dropdown from refcodes
         System.Web.HttpApplicationState app = System.Web.HttpContext.Current.Application;
         ICachePolicy cachePolicy = (ICachePolicy)app[Policy.Names.ApplicationCachePolicyKey];
         CDS.RefCodes refCodes = (RefCodes)cachePolicy.GetCachedObject( RefCodes.CacheKey );
         ArrayList budgetStaffRoleCodes = refCodes.GetRefCodes( "ClinicalTrialBudgetStaffRole" );
         rolesList.ID = "rolesList";
         rolesList.DataTextField = "Meaning";
         rolesList.DataValueField = "Code";
         rolesList.DataSource = budgetStaffRoleCodes;
         rolesList.DataBind( );
         if ( String.IsNullOrEmpty(budgetStaff.StudyStaffRoleCode) )
         {            
			//defaults to the first value in the list
			rolesList.SelectedIndex = 0;
         }
         else
         {
            rolesList.SelectedValue = budgetStaff.StudyStaffRoleCode;
         }
         rolesList.Items.Remove(new ListItem("N/A", "ClinicalTrialBudgetStaffRoleNA"));
         rolesList.AutoPostBack = true;
         rolesList.SelectedIndexChanged += new EventHandler(OnSelectedIndexChanged);		 

         // Setup validators
         rateFormatValidator = new RegularExpressionValidator( );
         rateFormatValidator.ErrorMessage = "Rate must be a valid dollar amount.";
         rateFormatValidator.Display = ValidatorDisplay.None;
         rateFormatValidator.ControlToValidate = inputRate.ID;
         rateFormatValidator.ValidationExpression = @"\d+\.{0,1}\d{0,2}";

         rateRequiredValidator = new RequiredFieldValidator( );
         rateRequiredValidator.ErrorMessage = "Rate is required.";
         rateRequiredValidator.Display = ValidatorDisplay.None;
         rateRequiredValidator.ControlToValidate = inputRate.ID;

         roleValidator = new RequiredFieldValidator( );
         roleValidator.ErrorMessage = "Role is required.";
         roleValidator.Display = ValidatorDisplay.None;
         roleValidator.ControlToValidate = rolesList.ID;

         otherRoleValidator = new RequiredFieldValidator( );
         otherRoleValidator.ErrorMessage = "Description for other role is required.";
         otherRoleValidator.Display = ValidatorDisplay.None;
         otherRoleValidator.ControlToValidate = inputRole.ID;

         // Call OnSelectedIndexChanged here to keep processing consistent with a user changing
         // the role, as we may have just set the selected value
         OnSelectedIndexChanged( this, EventArgs.Empty );

         inputRole.Text = budgetStaff.OtherRoleText;

         if ( budgetStaff.Rate != null )
         {
            inputRate.Text = budgetStaff.Rate;
         }

         tr = new TableRow( );
         tdRole = new TableCell( );
         tdRole.Controls.Add( roleValidator );
         tdRole.Controls.Add( otherRoleValidator );
         tdRole.Controls.Add( rolesList );
         tdRole.Controls.Add( inputRole );

         tdRate = new TableCell( );
         tdRate.Controls.Add( rateFormatValidator );
         tdRate.Controls.Add( rateRequiredValidator );
         tdRate.Controls.Add( inputRate );
         
         tdHours = new TableCell( );
         // Here we are getting details for this Budget Staff, both the total number of hours
         // and an indicator of whether the role is associated with any procedures at all.
         // Having 0 hours doesn't necessarily mean they aren't associated with any procedures
         // (because it may just not be set as required for any visits), so we want to use a
         // separate indicator for whether the role can be deleted
         SqlDataReader reader = DataAccess.ExecuteReader( DataAccess.GetConnectionString( ), "GetClinicalTrialBudgetStaffDetails",
            DataAccess.BuildSqlParameterArray( "@budgetId", SqlDbType.Int, budget.Id,
                                               "@budgetStaffId", SqlDbType.Int, budgetStaff.Id ) );

         while (reader.Read( ))
         {
            tdHours.Text = reader[0].ToString( );
         }

	     reader.Close();

         tdDelete = new TableCell( );
         tdDelete.Controls.Add( delete );

         tr.Controls.Add( tdRole );
         tr.Controls.Add( tdRate );
         tr.Controls.Add( tdHours );
         tr.Controls.Add( tdDelete );

         Controls.Add( tr );
      }

      /// <summary>
      /// Used to disable the delete checkbox if the staff has not been saved
      /// </summary>
      /// <param name="e"></param>
      protected override void OnPreRender(EventArgs e)
      {
         // Format numbers entered by the user
         if ( !String.IsNullOrEmpty(inputRate.Text) )
            inputRate.Text = decimal.Parse( inputRate.Text ).ToString( "f" );

         base.OnPreRender (e);
      }

      #endregion

      #region Event Handlers
      /// <summary>
      /// Event handler for user changing the role dropdown.  Used to setup controls.
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnSelectedIndexChanged(object sender, EventArgs e)
      {
         budgetStaff.StudyStaffRoleCode = rolesList.SelectedValue;
		 // Pre-defined role selected, display rate and hide "other" controls
		 System.Web.HttpApplicationState app = System.Web.HttpContext.Current.Application;
		 ICachePolicy cachePolicy = (ICachePolicy)app[Policy.Names.ApplicationCachePolicyKey];
		 CDS.RefCodes refCodes = (RefCodes)cachePolicy.GetCachedObject( RefCodes.CacheKey );
		 RefCode refCode = refCodes.GetRefCode( "ClinicalTrialBudgetStaffRole", rolesList.SelectedValue );

         if ( budgetStaff.StudyStaffRoleCode != "ClinicalTrialBudgetStaffRoleOther")
         {  
            inputRate.Text = refCode.Attributes["Rate"].ToString( );
            rolesList.CssClass = "ExpandControl";
            inputRole.CssClass = "ControlHidden";
            otherRoleValidator.Enabled = false;
         }         
         else
         {
            // Other selected, enable controls
			otherRoleValidator.Enabled = true;            
            rolesList.CssClass = "ShortenControl";
            inputRole.CssClass = "ControlShown";
         }
      }
      #endregion
   }

   #region Class BudgetStaffControlDesigner
   /// <summary>
   /// Designer associated with the BudgetStaffControl control.
   /// </summary>
   /// <remarks>
   /// This class cannot be used directly.
   /// </remarks>
   public class BudgetStaffControlDesigner : ControlDesigner
   {
      #region Overrides
      /// <summary>
      /// Since the BudgetStaffControl control does not have any design-time visibility, the designer provides
      /// the type name of that control and the name of the instance.
      /// </summary>
      /// <returns>HTML representation of the BudgetStaffControl control</returns>
      public override string GetDesignTimeHtml( )
      {
         return CreatePlaceHolderDesignTimeHtml( );
      }
      #endregion
   }
   #endregion
}
